#pragma once

#include <vector>
#include <memory>
#include "rtda/heap/class_member.h"
#include "classfile/class_file.hpp"
#include "rtda/heap/method_descriptor_parser.h"
#include "rtda/heap/exception_table.h"

namespace jvm {
namespace heap {

class Method : public ClassMember {
private:
    uint32_t m_maxStack = 0;
    uint32_t m_maxLocals = 0;
    std::vector<uint8_t> m_code;
    uint32_t m_argSlotCount = 0;
    //ExceptionTable m_exceptionTable;
    std::shared_ptr<ExceptionTable> m_pExceptionTable;
    std::shared_ptr<classfile::LineNumberTableAttribute> m_pLineNumberTable;

public:
    Method(std::shared_ptr<Class> pClass, const std::shared_ptr<classfile::MemberInfo> pMemberInfo);
    static std::vector<std::shared_ptr<Method>> newMethods(std::shared_ptr<Class> pClass, const std::vector<std::shared_ptr<classfile::MemberInfo>>& cfMethods);

    //static std::shared_ptr<Method> newMethod(std::shared_ptr<Class> pClass, const std::shared_ptr<classfile::MemberInfo> pMemberInfo);

    
    
    // Access flags
    bool isSynchronized() const;
    bool isBridge() const;
    bool isVarargs() const;
    bool isNative() const;
    bool isAbstract() const;
    bool isStrict() const;
    
    // Getters
    uint32_t getMaxStack() const;
    uint32_t getMaxLocals() const;
    const std::vector<uint8_t>& getCode() const;
    uint32_t getArgSlotCount() const;

    int getLineNumber(const int& pc) const;

    int findExceptionHandler(std::shared_ptr<Class> pExClass, const int& pc) const;

private:
    void copyAttributes(const std::shared_ptr<classfile::MemberInfo> pMemberInfo);

    void calcArgSlotCount(const std::unique_ptr<MethodDescriptor>& parsedDescriptor);

    void injectCodeAttribute(const std::string& returnType);
};

} // namespace heap
} // namespace jvm
